package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.system.DTO.Reques.user.LoginUserDTO;
import com.ruoyi.system.mapper.RoleMapper;
import com.ruoyi.system.mapper.UserMapper;
import com.ruoyi.system.pojo.user.Role;
import com.ruoyi.system.pojo.user.User;
import com.ruoyi.system.pojo.vo.RoleVO;
import com.ruoyi.system.pojo.vo.UserVO;
import com.ruoyi.system.service.UserService;
import com.ruoyi.system.utils.LoginUtils;
import com.ruoyi.system.utils.PageResult;
import com.ruoyi.system.utils.UserConvertUtil;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Description:
 *
 * @author JourWon
 * @date Created on 2025/5/13
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private ModelMapper modelMapper;

    @DS("master")
    @Override
    public Object login(LoginUserDTO loginUserDTO) {
        try {
            // 验证验证码
            String redisCode = redisTemplate.opsForValue().get("code:");
            LoginUtils.validateCaptcha(loginUserDTO.getCode(), redisCode);

            // 获取并校验用户
            User user = getUserByIdentifier(loginUserDTO);
            LoginUtils.validateUserStatus(user);
            LoginUtils.validatePassword(loginUserDTO.getPassword(), user.getPassword());

            // 生成token
            String token = generateToken(user);
            // 缓存用户信息
            cacheUserToken(user, token);

            // 返回信息
            return UserConvertUtil.convertToLoginResponse(user, token);
        } catch (ServiceException e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @DS("master")
    @Override
    public PageResult<UserVO> searchUsers(Integer pageIndex, Integer pageSize, String userName, Integer roleId, Boolean isRepair) {
        // 设置默认值
        if (pageIndex == null || pageIndex < 1) {
            pageIndex = 1;
        }
        if (pageSize == null || pageSize < 1) {
            pageSize = 10;
        }

        // 计算总数和总页数
        int totalCount = userMapper.countByCondition(userName, roleId, isRepair);
        int totalPage = (int) Math.ceil((double) totalCount / pageSize);

        // 计算偏移量
        int offset = (pageIndex - 1) * pageSize;

        // 查询数据
        List<User> userList = userMapper.searchByPage(userName, roleId, isRepair, offset, pageSize);

        // 转换为VO对象
        List<UserVO> records = userList.stream()
                .map(user -> {
                    UserVO userVO = modelMapper.map(user, UserVO.class);
                    // 设置角色信息
                    Role role = roleMapper.selectById(user.getRoleId());
                    if (role != null) {
                        userVO.setRole(modelMapper.map(role, RoleVO.class));
                    }
                    return userVO;
                })
                .collect(Collectors.toList());

        // 构建返回结果
        PageResult<UserVO> result = new PageResult<>();
        result.setPageIndex(pageIndex);
        result.setPageSize(pageSize);
        result.setTotalPage(totalPage);
        result.setTotalCount(totalCount);
        result.setCurrentPageRecords(records);

        return result;
    }

    /**
     * 根据登录标识(用户名/手机号)获取用户
     * @param dto
     * @return
     */
    private User getUserByIdentifier(LoginUserDTO dto) {
        // 参数校验
        if (StringUtils.isEmpty(dto.getPassword())) {
            throw new ServiceException("密码不能为空");
        }

        // 判断是手机号登录还是用户名登录
        if (StringUtils.isNotEmpty(dto.getAccount())) {
            // 手机号登录
            if (!dto.getAccount().matches("^1[3-9]\\d{9}$")) {
                throw new ServiceException("手机号格式不正确");
            }
            return userMapper.selectUserByMobile(dto.getAccount());
        } else if (StringUtils.isNotEmpty(dto.getLoginName())) {
            // 用户名登录
            return userMapper.selectUserByUserName(dto.getLoginName());
        } else {
            throw new ServiceException("登录名或手机号不能为空");
        }
    }

    /**
     * 缓存用户Token
     * @param user
     * @param token
     */
    private void cacheUserToken(User user, String token) {
        // Token缓存
        redisTemplate.opsForValue().set(
                "token:" + token,
                user.getId().toString(),
                30, TimeUnit.MINUTES);

        // 用户信息缓存
        redisTemplate.opsForValue().set(
                "user:" + user.getId(),
                JSON.toJSONString(user),
                30, TimeUnit.MINUTES);
    }

    /**
     * 生成JWT Token
     * @param user
     * @return
     */
    private String generateToken(User user) {
        return Jwts.builder()
                .setSubject(user.getLoginName())
                .setId(user.getId().toString())
                .signWith(SignatureAlgorithm.HS512, "123456")
                .setExpiration(new java.util.Date(System.currentTimeMillis() + 5 * 60 * 1000))
                .compact();
    }
}
